06. 문장수준 읽기 일관성
(1) 문장수준 읽기 일관성이란?
- 단일 SQL문이 수행되는 도중에 다른 트랜잭션에 의해 데이터의 추가, 변경, 삭제가 발생하더라도 일관성 있는 결과집합을 리터하는 것.
- 타DBMS는 모두 로우 Lock을 사용해 Dirty Read를 방지. 읽기 작업에 대해 Shared Lock을 사용함으로써, Exclusive Lock이 걸린 로우를 읽지 못하도록 한다.
<사례1, 2 p.48~51 참고>
(2) Consistent 모드 블록 읽기 <p.52 그림 1-14 참고>
(3) Consistent 모드 블록 읽기의 세부원리
- 오라클에서 수행되는 모든 쿼리는 Global 변수인 SCN(System Commit Number)값을 먼저 확인하고 읽기 작업 시작(쿼리 SCN, 스냅샷 SCN)
- 읽는 블록마다 블록 SCN과 비교해 읽을 수 있는 버전인지를 판단
A. 'Current 블록 SCN <= 쿼리SCN' 이고, commited 상태
- 쿼리가 시작된 이후에 해당 블록에 변경이 가해지지 않았다는 것을 의미. CR블록을 생성하지 않고 Current 블록을 그대로 읽는다.
- Consistent 모드에서 데이터를 읽을 때는 블록 SCN(System Change Number)이 쿼리 SCN(System Commit Number)보다 작거나 같은 블록만 읽을 수 있다.
- 이때의 블록은 Current 블록을 의미하며, Current 블록은 오직 한 개뿐이다. 데이터 갱신은 항상 Current 블록에서만 발생.
B. 'Current 블록 SCN > 쿼리SCN' 이고, commited 상태
- 쿼리가 시작된 이후 해당 블록에 변경이 가해지고 커밋되었다는 것을 의미. <p.55 그림 1-15 참고>
1) 블록 원본에 해당하는 Current 블록의 SCN이 쿼리 SCN보다 크다.
2) 블록 복사본에 해당하는 CR블록을 먼저 생성(CR Cloning)
3) 자신이 읽을 수 있는 과거 버전(쿼리 SCN보다 낮은 마지막 commited 시점)으로 되돌린다.(ITL 슬록에서 UBA(Undo Block Address)가 가리키는 Undo 블록 이용) - Undo 레코드를 읽어 CR 블록을 한 단계 이전 상태로 되돌렸는데, 거기에 커밋되지 않은 변경사항이 포함돼 있거나 블록 SCN이 높다면 다시 ITL 슬롯에 있는
UBA가 가리키는 Undo 레코드를 찾아 블록을 이전 상태로 되돌리는 작업을 계속한다. - 최종적으로 완성된 버전의 CR블록은, 블록 SCN이 쿼리 SCN보다 작으면서 커밋되지 않은 내용은 전혀 포함하지 않은 상태가 된다.
- UBA를 통해 계속적인 롤백이 가능한 것은 ITL에 대한 변경내역까지도 Undo 레코드에 기록되기 때문.
- 같은 레코드를 계속 변경할 때, 그 레코드를 조회하는 다른 세션에서의 CR블록 읽기 횟수도 계속 증가하는 것을 통해 확인 가능.
- 10g부터는 IMU(In-Memory Undo) 메커니즘 작동하므로 CR 롤백을 위해 Undo를 참조하지 않고 Shared Pool 내의 IMU Pool에 저장된 값을 이용(IMU CR rollback)
- CR 블록을 과거 상태로 되돌리는 과정에서 필요한 Undo 정보가 덮어 쓰여져 계속 롤백을 진행할 수 없을 때 'Snapshot too old(ora-1555)' 발생
- Delayed 블록 클린아웃' 과정에서 트랜잭션 테이블 슬롯이 이미 다른 트랜잭션에 의해 재사용되는 바람에 현재 읽고자 하는 클린아웃되지 않은 블록의 정확한
커밋 시점 정보를 확인할 수 없을 때도 Snapshot too old' 발생.(8, 9절에서 설명)
- A세션
SQL> alter session set "_in_memory_undo" = false;
SQL> update emp set sal = sal + 1 where empno = 7900;
혹은
SQL> declare
2 l_cnt number;
3 begin
4 for l_cnt in 1..1000
5 loop
6 update emp set sal = sal + 1 where empno = 7900;
7 end loop;
8 end;
9 /
PL/SQL 처리가 정상적으로 완료되었습니다.
SQL> update emp set sal = sal + 1 where empno = 7900;
1 행이 갱신되었습니다.
SQL> /
1 행이 갱신되었습니다.
SQL> /
1 행이 갱신되었습니다.
- B세션
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
926 consistent gets
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
927 consistent gets
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
928 consistent gets
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
929 consistent gets
IMU(In-Memory Undo)
- 10g에 추가된 기능으로 Hidden 파라미터 '_in_memory_undo'와 '_imu_pools'에 의해 제어
- 이 파라미터가 TRUE면 오라클은 Undo 데이터를 Undo에 세그먼트가 아닌 Shared Pool 내의 미리 할당된 IMU Pool(KTI-Undo)에 생성
- 각 Pool은 하나의 트랜잭션에 전용으로 할당되며 im memory undo latch에 의해 보호
- IMU Pool이 다 차면 그때까지 저장해 둔 Undo 데이터를 Undo 세그먼트로 일괄 기록하며(IMU Flush), 이후 계속 발생하는 Undo 데이터는 예전처럼 Undo 세그먼트에 저장
- IMU는 작은 트랜잭션을 위해 고안된 기능이며, Undo 세그먼트 헤더 블록과 Undo 세그먼트 블록 버퍼에 대한 래치 경합 및 Pinning을 줄일 수 있다.
Please enter THE PARAMETER : _imu_pools
NAME VALUE ISDEFAULT ISSES_MODIFIABLE ISSYS_MODIFIABLE ISMODIFIED ISADJUSTED DESCRIPTION
-
--
-
-
_imu_pools 3 TRUE false false false false in memory undo pools
Please enter THE PARAMETER : _in_memory_undo
NAME VALUE ISDEFAULT ISSES_MODIFIABLE ISSYS_MODIFIABLE ISMODIFIED ISADJUSTED DESCRIPTION
-
--
-
---
_in_memory_undo TRUE TRUE true immediate false false Make in memory undo for top level transactions
C.'Current 블록이 Active상태, 즉 갱신이 진행 중인 것으로 표시'돼 있을때
- 읽으려는 레코드에 Lock Byte가 설정돼 있는데, ITL에 아직 커밋 정보가 기록되지 않았다면 현재 갱신이 진행중(Active)인 것으로 인식할 수 있다.
- 오라클은 커밋 시 항상 곧바로 블록을 클린아웃(트랜잭션에 의해 설정된 로우 Lock을 해제하고 블록 헤더에 커밋 정보를 기록)하지는 않는다.
따라서 Active 상태의 블록일 때는 일단 트랜잭션 테이블로부터 커밋정보를 가져와 블록 클린아웃을 시도한다. - 쿼리 SCN 이전에 이미 커밋된 블록 : A경우처럼 그 블록을 그대로 읽는다.
- 쿼리 SCN 이후에 커밋된 블록으로 확인되거나, 커밋되지 않아 아직 클린아웃할 수 없는 경우 :
B경우처럼 CR Copy를 만들어 쿼리 SCN보다 낮은 마지막 Committed 상태로 되돌린 후 읽는다.
<A, B, C 상황 예시는 p.58 ~ p.61 참고>
DBA당 CR 개수 제한
- 하나의 데이터 블록마다 6개까지만 CR Copy를 허용. '_db_block_max_cr_dba' 파라미터로 제어.
- CR Copy는 LRU 리스트 상에서 항상 LRU end쪽에 위치하기 때문에 Free 버퍼가 필요할 때 1순위로 밀려난다.
문서에 대하여
- 최초작성자 : 김종원
- 최초작성일 : 2009년 10월 23일
- 이 문서는 오라클클럽 코어 오라클 데이터베이스 스터디 모임에서 작성하였습니다.
- {*}이 문서의 내용은 (주)비투엔컬설팅에서 출간한 '오라클 성능 고도화 원리와 해법I'를 참고하였습니다.*